package com.wolfsea.flowlayoutdemo
import android.content.Context
import android.text.TextPaint
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.get

/**
 *@desc FlowLayout
 *@author liuliheng
 *@time 2022/11/27  21:20
 **/
class FlowLayout @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null) :
    ConstraintLayout(context, attributeSet) {

    private val contentTvMap = mutableMapOf<Int, AppCompatTextView?>()
    private val contentIvMap = mutableMapOf<Int, AppCompatImageView?>()

    private val convertContentTvMap = mutableMapOf<Int, AppCompatTextView?>()
    private val convertContentIvMap = mutableMapOf<Int, AppCompatImageView?>()

    private val rootViewMap = mutableMapOf<Int, View>()

    private val translationXIndexList = mutableListOf<Int>()

    private var clickViewIndex = -1
    private var maxStrWidth = 0
    private var specialStrWidth = 0

    private var textPaint = TextPaint().apply {
        isAntiAlias = true
        isDither = true
        textSize = context.resources.getDimension(R.dimen.sp_15)
    }

    /*
    *   1.view扩充宽度后  内容不居中 ---  已完成
    *   2.内容长度过长导致排列问题 --- 已完成
    *   3.增加长按事件 长按后背景改变  显示删除按钮---已完成
    *   4.点击删除按钮可删除 --- 已完成
    * */
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        setMeasuredDimension(
            MeasureSpec.getSize(widthMeasureSpec),
            MeasureSpec.getSize(heightMeasureSpec)
        )
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        var j = 0
        var usedWidth = 0
        var usedHeight = 0
        var resetViewWidth = false
        var lastViewWidth: Int
        translationXIndexList.clear()
        Log.d(TAG, "childCount:${childCount}")
        while (j < childCount) {
            val view = get(j)
            Log.d(TAG, "j-order000:${j}")
            var viewWidth = view.measuredWidth
            val calcViewWidth = viewWidth
            val viewHeight = view.measuredHeight
            val layoutParams = view.layoutParams as ConstraintLayout.LayoutParams
            val marginTop = layoutParams.topMargin
            val marginLeft = layoutParams.leftMargin
            val beyondWidth = viewWidth + marginLeft > width - usedWidth
            Log.d(TAG, "beyondWidth:${beyondWidth}")
            if (resetViewWidth || beyondWidth) {
                viewWidth = width - usedWidth - marginLeft * 2
            }
            view.layout(
                marginLeft + usedWidth,
                usedHeight + marginTop ,
                viewWidth + marginLeft + usedWidth,
                viewHeight + marginTop + usedHeight
            )

            lastViewWidth = viewWidth + marginLeft
            usedWidth += lastViewWidth

            if (resetViewWidth || beyondWidth) {
                usedWidth = 0
                usedHeight += marginTop + viewHeight
                //平移居中显示
                val translationXValue = (viewWidth - calcViewWidth).toFloat() / 2
                Log.d(TAG, "trans--j:${j}--->translationX:${translationXValue}")
                if (convertContentIvMap[j] == null || convertContentTvMap[j] == null) {
                    contentTvMap[j]?.translationX = translationXValue
                    contentIvMap[j]?.translationX = translationXValue
                } else {
                    convertContentTvMap[j]?.translationX = translationXValue
                    convertContentIvMap[j]?.translationX = translationXValue
                }
                translationXIndexList.add(j)
            }

            resetViewWidth = false

            if (j + 1 < childCount) {
                val nextView = get(j + 1)
                val nextViewWidth = nextView.measuredWidth
                //val nextViewHeight = view.measuredHeight
                //val nextViewLayoutParams = view.layoutParams as ConstraintLayout.LayoutParams
                //val nextViewMarginTop = layoutParams.topMargin
                val nextViewMarginLeft = layoutParams.leftMargin
                if (nextViewMarginLeft + nextViewWidth >= width - usedWidth) {
                    Log.d(TAG, "nextView beyond height")
                    resetViewWidth = true
                    j -= 1
                    Log.d(TAG, "j-order111:${j}")
                    usedWidth -= lastViewWidth
                } else {
                    resetViewWidth = false
                }
            }
            j++
        }
    }

    override fun onFinishInflate() {
        super.onFinishInflate()

        maxStrWidth = textPaint.measureText(STANDARD_STR).toInt()
        specialStrWidth = textPaint.measureText(SPECIAL_STR).toInt()

        //val str1 = "美国著名新闻社交网站"
        //val str2 = "Facebook母公司Meta于28日被爱尔兰数据保护委员会DPC罚款2.65亿欧元约合2.77亿美元"
        val str1 = "既定的子任务调度过程中会观察相对应的时"
        //val str2 = "adsdfasdfsffdsafsafsaASDSEWQFQFFFQre"
        val str2 = "取消闰秒"
        val str3 = "世界时"
        val str4 = "大会决定"
        val str5 = "几毫秒误差"
        val str6 = "闰秒问题"
        val str7 = "既定的子任务"
        val str8 = "废除"
        val str9 = "时间条件不匹配"
        val str00 = "平滑升级"
        val str01 = "胖哥"
        val str02 = "5700"

        val strList = mutableListOf<String>()
        strList.add(str1)
        strList.add(str2)
        strList.add(str3)
        strList.add(str4)
        strList.add(str5)
        strList.add(str6)
        strList.add(str7)
        strList.add(str8)
        strList.add(str9)
        strList.add(str00)
        strList.add(str01)
        strList.add(str02)

        addContent(strList)
    }


    private fun addContent(contents: MutableList<String>) {
        for (index in contents.indices) {
            val flowLayout = LayoutInflater.from(context).inflate(R.layout.flow_layout, this, false)
            flowLayout.tag = index
            rootViewMap[index] = flowLayout

            val clRootFlowLayout = flowLayout.findViewById<ConstraintLayout>(R.id.cl_root_flow_layout)
            clRootFlowLayout.setOnClickListener {
                if (clickViewIndex == index) {
                    return@setOnClickListener
                }
                clickViewIndex = index
                for (transIndexValue in translationXIndexList) {
                    contentTvMap[transIndexValue]?.translationX = 0f
                    contentIvMap[transIndexValue]?.translationX = 0f
                }

                for ((itemIndex, itemView) in contentIvMap) {
                    itemView?.visibility = if (clickViewIndex == itemIndex) View.VISIBLE else View.GONE
                }
            }

            val tvContent = flowLayout.findViewById<AppCompatTextView>(R.id.flow_tv)
            //tvContent.text = contents[index]
            tvContent.text = cutOffedStrContent(contents[index])
            contentTvMap[index] = tvContent

            val ivContent = flowLayout.findViewById<AppCompatImageView>(R.id.flow_iv)
            ivContent.setOnClickListener {
                for (transIndexValue in translationXIndexList) {
                    contentTvMap[transIndexValue]?.translationX = 0f
                    contentIvMap[transIndexValue]?.translationX = 0f

                    convertContentTvMap[transIndexValue]?.translationX = 0f
                    convertContentIvMap[transIndexValue]?.translationX = 0f
                }

                contentIvMap[clickViewIndex] = null
                contentTvMap[clickViewIndex] = null

                /*重新排列item中的子view*/
                var newIndex = 0
                convertContentTvMap.clear()
                convertContentIvMap.clear()
                for ((itemIndex, itemView) in contentIvMap) {
                    if (itemView != null) {
                        convertContentIvMap[newIndex] = contentIvMap[itemIndex]
                        convertContentTvMap[newIndex] = contentTvMap[itemIndex]
                        newIndex++
                    }
                }

                /*找到要删除item的索引*/
                var viewIndex = -1
                for (i in 0.until(childCount)) {
                    val childInLayout = get(i)
                    val tagI = childInLayout.tag as Int
                    val tagJ = rootViewMap[clickViewIndex]?.tag as Int
                    if (tagI == tagJ) {
                        viewIndex = i
                        break
                    }
                }

                if (viewIndex != -1) {
                    val removedView = get(viewIndex)
                    removeView(removedView)
                }
            }
            contentIvMap[index] = ivContent

            addView(
                flowLayout,
                ConstraintLayout.LayoutParams(
                    ConstraintLayout.LayoutParams(
                        ConstraintLayout.LayoutParams.WRAP_CONTENT,
                        ConstraintLayout.LayoutParams.WRAP_CONTENT
                    ).apply {
                        topMargin = context.resources.getDimension(R.dimen.dp_10).toInt()
                        leftMargin = context.resources.getDimension(R.dimen.dp_10).toInt()
                    }
                )
            )
        }
    }

    private fun cutOffedStrContent(content: String): String {
        val measureContentWidth = textPaint.measureText(content).toInt()
        Log.d(TAG, "maxStrWidth:${maxStrWidth},measureContentWidth:${measureContentWidth}")
        return if (measureContentWidth <= maxStrWidth) {
            content
        } else {
            val contentLength = content.length
            var start = 0
            var end = contentLength
            var calContentLength = 0
            var fromLeft = false
            while (start < end) {

                val leftSubStrWidth = textPaint.measureText(content.substring(start, start + 1)).toInt()
                calContentLength += leftSubStrWidth
                if (calContentLength > maxStrWidth) {
                    fromLeft = true
                    break
                }
                start++


                val rightSubStrWidth = textPaint.measureText(content.substring(end - 1, end)).toInt()
                calContentLength += rightSubStrWidth
                if (calContentLength > maxStrWidth) {
                    fromLeft = false
                    break
                }
                end--
            }

            Log.d(TAG, "fromLeft:${fromLeft}")
            if (fromLeft) {
                val builder = StringBuilder()
                val leftStr = content.substring(0, start - 1)
                val rightStr = content.substring(end, contentLength)
                builder.append(leftStr).append(SPECIAL_STR).append(rightStr).toString()
            } else {
                val builder = StringBuilder()
                val leftStr = content.substring(0, start)
                val rightStr = content.substring(end + 1, contentLength)
                builder.append(leftStr).append(SPECIAL_STR).append(rightStr).toString()
            }
        }
    }

    companion object {
        const val TAG = "FlowLayout"
        const val SPECIAL_STR = "..."
        const val STANDARD_STR = "既定的子任务调度过程中会观察相对应的时"
    }

}